﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Web;
using System.Xml;
using MySql.Data.MySqlClient;

namespace eSYSU.Weibo
{
    /// <summary>
    /// 新浪微博XML文件处理类
    /// </summary>
    public class SinaWeiboHandler
    {
        /// <summary>
        /// 要获取的微博内容类型
        /// </summary>
        public enum WeiboType
        {
            //[Description("获取最新的公共微博消息")]
            //statuses/public_timeline,
            //statuses/friends_timeline,     /*获取当前登录用户及其所关注用户的最新微博消息 (别名: statuses/home_timeline)*/
            //user = "statuses/user_timeline",           /*获取当前登录用户发布的微博消息列表*/
            //comments = "statuses/comments_timeline",   /*获取当前用户发送及收到的评论列表*/
            //comments_s = "statuses/comments_by_me",    /*获取当前用户发出的评论*/
            //comments_r = "statuses/comments_to_me"     /*获取当前用*/
        }

        public SinaWeiboHandler()
        {
            //
            //TODO: 在此处添加构造函数逻辑
            //
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="xmlUser"></param>
        /// <returns></returns>
        public static SinaWeiboUsers GetModelByUserXml(string xmlUser)
        {
            if (!string.IsNullOrEmpty(xmlUser))
            {
                WeiboXMLHandler xml = new WeiboXMLHandler();
                xml.LoadXml(xmlUser);

                SinaWeiboUsers user = new SinaWeiboUsers();
                foreach (XmlNode xuser in xml.SelectNodes("//user"))
                {
                    long user_id = long.TryParse(xml.SelectSingleNode(xuser, "id"), out user_id) ? user_id : 0;
                    string screen_name = xml.SelectSingleNode(xuser, "screen_name");
                    string name = xml.SelectSingleNode(xuser, "name");
                    string description = xml.SelectSingleNode(xuser, "description");
                    string province = xml.SelectSingleNode(xuser, "province");
                    string city = xml.SelectSingleNode(xuser, "city");
                    string location = xml.SelectSingleNode(xuser, "location");
                    string url = xml.SelectSingleNode(xuser, "url");
                    string profile_image_url = xml.SelectSingleNode(xuser, "profile_image_url");
                    string domain = xml.SelectSingleNode(xuser, "domain");
                    string gender = xml.SelectSingleNode(xuser, "gender");
                    long followers_count = long.TryParse(xml.SelectSingleNode(xuser, "followers_count"), out followers_count) ? followers_count : 0;
                    long friends_count = long.TryParse(xml.SelectSingleNode(xuser, "friends_count"), out friends_count) ? friends_count : 0;
                    long statuses_count = long.TryParse(xml.SelectSingleNode(xuser, "statuses_count"), out statuses_count) ? statuses_count : 0;
                    long favourites_count = long.TryParse(xml.SelectSingleNode(xuser, "favourites_count"), out favourites_count) ? favourites_count : 0;
                    bool following = bool.TryParse(xml.SelectSingleNode(xuser, "following"), out following) ? following : false;
                    bool verified = bool.TryParse(xml.SelectSingleNode(xuser, "verified"), out verified) ? verified : false;
                    DateTime created_at = DateTime.TryParse(xml.SelectSingleNode(xuser, "created_at"), out created_at) ? created_at : DateTime.Now;
                    //created_at = Convert.ToDateTime(xml.SelectSingleNode(xuser, "created_at"));
                    //DateTime.TryParse(

                    user.id = user_id;
                    user.screen_name = screen_name;
                    user.name = name;
                    user.description = description;
                    user.province = province;
                    user.city = city;
                    user.location = location;
                    user.url = url;
                    user.profile_image_url = profile_image_url;
                    user.domain = domain;
                    user.gender = gender;

                    user.followers_count = followers_count;
                    user.friends_count = friends_count;
                    user.statuses_count = statuses_count;
                    user.favourites_count = favourites_count;
                    user.following = following;
                    user.verified = verified;
                    user.created_at = created_at;
                }
                return user;
            }
            return null;
        }



        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="xmlUser"></param>
        /// <returns></returns>
        public static SinaWeiboUsers GetModelByUserXml(XmlNode xnUser)
        {
            WeiboXMLHandler xml = new WeiboXMLHandler();
            SinaWeiboUsers user = new SinaWeiboUsers();

            long user_id = long.TryParse(xml.SelectSingleNode(xnUser, "id"), out user_id) ? user_id : 0;
            string screen_name = xml.SelectSingleNode(xnUser, "screen_name");
            string name = xml.SelectSingleNode(xnUser, "name");
            string description = xml.SelectSingleNode(xnUser, "description");
            string province = xml.SelectSingleNode(xnUser, "province");
            string city = xml.SelectSingleNode(xnUser, "city");
            string location = xml.SelectSingleNode(xnUser, "location");
            string url = xml.SelectSingleNode(xnUser, "url");
            string profile_image_url = xml.SelectSingleNode(xnUser, "profile_image_url");
            string domain = xml.SelectSingleNode(xnUser, "domain");
            string gender = xml.SelectSingleNode(xnUser, "gender");
            long followers_count = long.TryParse(xml.SelectSingleNode(xnUser, "followers_count"), out followers_count) ? followers_count : 0;
            long friends_count = long.TryParse(xml.SelectSingleNode(xnUser, "friends_count"), out friends_count) ? friends_count : 0;
            long statuses_count = long.TryParse(xml.SelectSingleNode(xnUser, "statuses_count"), out statuses_count) ? statuses_count : 0;
            long favourites_count = long.TryParse(xml.SelectSingleNode(xnUser, "favourites_count"), out favourites_count) ? favourites_count : 0;
            bool following = bool.TryParse(xml.SelectSingleNode(xnUser, "following"), out following) ? following : false;
            bool verified = bool.TryParse(xml.SelectSingleNode(xnUser, "verified"), out verified) ? verified : false;
            DateTime created_at = DateTime.TryParse(xml.SelectSingleNode(xnUser, "created_at"), out created_at) ? created_at : DateTime.Now;
            //created_at = Convert.ToDateTime(xml.SelectSingleNode(xuser, "created_at"));
			created_at = eSYSU.Web.Common.StringHelper.FormatSinaWeiboDateTime(xml.SelectSingleNode(xnUser, "created_at"));

            user.id = user_id;
            user.screen_name = screen_name;
            user.name = name;
            user.description = description;
            user.province = province;
            user.city = city;
            user.location = location;
            user.url = url;
            user.profile_image_url = profile_image_url;
            user.domain = domain;
            user.gender = gender;

            user.followers_count = followers_count;
            user.friends_count = friends_count;
            user.statuses_count = statuses_count;
            user.favourites_count = favourites_count;
            user.following = following;
            user.verified = verified;
            user.created_at = created_at;

            return user;
        }



        /// <summary>
        /// 获取微博信息内容
        /// </summary>
        /// <param name="sStatusXML">包含微博信息内容的XML字符串</param>
        /// <returns>微博信息内容</returns>
        public static SinaWeiboStatuses GetModeByStatusXML(string sStatusXML)
        {

            if (!string.IsNullOrEmpty(sStatusXML))
            {
                WeiboXMLHandler xml = new WeiboXMLHandler();
                xml.LoadXml(sStatusXML);

                SinaWeiboStatuses statuses = new SinaWeiboStatuses();
                foreach (XmlNode xn in xml.SelectNodes("//status"))
                {
                    long id = long.TryParse(xml.SelectSingleNode(xn, "id"), out id) ? id : 0;
                    string text = xml.SelectSingleNode(xn, "text");
                    string source = xml.SelectSingleNode(xn, "source");
                    bool favorited = bool.TryParse(xml.SelectSingleNode(xn, "favorited"), out favorited) ? favorited : false;
                    bool truncated = bool.TryParse(xml.SelectSingleNode(xn, "truncated"), out truncated) ? truncated : false;
                    long in_reply_to_status_id = long.TryParse(xml.SelectSingleNode(xn, "in_reply_to_status_id"), out in_reply_to_status_id) ? in_reply_to_status_id : 0;
                    long in_reply_to_user_id = long.TryParse(xml.SelectSingleNode(xn, "in_reply_to_user_id"), out in_reply_to_user_id) ? in_reply_to_user_id : 0;
                    string in_reply_to_screen_name = xml.SelectSingleNode(xn, "in_reply_to_screen_name");
                    string original_pic = xml.SelectSingleNode(xn, "original_pic");
                    string thumbnail_pic = xml.SelectSingleNode(xn, "thumbnail_pic");
                    long retweeted_status_id = long.TryParse(xml.SelectSingleNode(xn, "retweeted_status_id"), out retweeted_status_id) ? retweeted_status_id : 0;
                    long user_id = long.TryParse(xml.SelectSingleNode(xn, "user_id"), out user_id) ? user_id : 0;
                    DateTime created_at = DateTime.TryParse(xml.SelectSingleNode(xn, "created_at"), out created_at) ? created_at : DateTime.Now;
                    //created_at = Convert.ToDateTime(xml.SelectSingleNode(xuser, "created_at"));
					created_at = eSYSU.Web.Common.StringHelper.FormatSinaWeiboDateTime(xml.SelectSingleNode(xn, "created_at"));

                    statuses.id = id;
                    statuses.user_id = user_id;
                    statuses.text = text;
                    statuses.source = source;
                    statuses.favorited = favorited;
                    statuses.truncated = truncated;
                    statuses.in_reply_to_status_id = in_reply_to_status_id;
                    statuses.in_reply_to_user_id = in_reply_to_user_id;
                    statuses.in_reply_to_screen_name = in_reply_to_screen_name;
                    statuses.created_at = created_at;
                    statuses.original_pic = original_pic;
                    statuses.thumbnail_pic = thumbnail_pic;
                    statuses.retweeted_status_id = retweeted_status_id;
                }
                return statuses;
            }
            return null;
        }


        /// <summary>
        /// 获取微博信息内容
        /// </summary>
        /// <param name="xnStatus">包含微博信息内容的XmlNode节点</param>
        /// <returns>微博信息内容</returns>
        public static SinaWeiboStatuses GetModeByStatusXML(XmlNode xnStatus)
        {
            WeiboXMLHandler xml = new WeiboXMLHandler();
            SinaWeiboStatuses statuses = new SinaWeiboStatuses();

            long id = long.TryParse(xml.SelectSingleNode(xnStatus, "id"), out id) ? id : 0;
            long user_id = long.TryParse(xml.SelectSingleNode(xnStatus, "user_id"), out user_id) ? user_id : 0;
            string text = xml.SelectSingleNode(xnStatus, "text");
            string source = xml.SelectSingleNode(xnStatus, "source");
            bool favorited = bool.TryParse(xml.SelectSingleNode(xnStatus, "favorited"), out favorited) ? favorited : false;
            bool truncated = bool.TryParse(xml.SelectSingleNode(xnStatus, "truncated"), out truncated) ? truncated : false;
            long in_reply_to_status_id = long.TryParse(xml.SelectSingleNode(xnStatus, "in_reply_to_status_id"), out in_reply_to_status_id) ? in_reply_to_status_id : 0;
            long in_reply_to_user_id = long.TryParse(xml.SelectSingleNode(xnStatus, "in_reply_to_user_id"), out in_reply_to_user_id) ? in_reply_to_user_id : 0;
            string in_reply_to_screen_name = xml.SelectSingleNode(xnStatus, "in_reply_to_screen_name");
            string original_pic = xml.SelectSingleNode(xnStatus, "original_pic");
            string thumbnail_pic = xml.SelectSingleNode(xnStatus, "thumbnail_pic");
            long retweeted_status_id = long.TryParse(xml.SelectSingleNode(xnStatus, "retweeted_status_id"), out retweeted_status_id) ? retweeted_status_id : 0;
            DateTime created_at = DateTime.TryParse(xml.SelectSingleNode(xnStatus, "created_at"), out created_at) ? created_at : DateTime.Now;
            //created_at = Convert.ToDateTime(xml.SelectSingleNode(xuser, "created_at"));
			created_at = eSYSU.Web.Common.StringHelper.FormatSinaWeiboDateTime(xml.SelectSingleNode(xnStatus, "created_at"));

            statuses.id = id;
            statuses.user_id = user_id;
            statuses.text = text;
            statuses.source = source;
            statuses.favorited = favorited;
            statuses.truncated = truncated;
            statuses.in_reply_to_status_id = in_reply_to_status_id;
            statuses.in_reply_to_user_id = in_reply_to_user_id;
            statuses.in_reply_to_screen_name = in_reply_to_screen_name;
            statuses.created_at = created_at;
            statuses.original_pic = original_pic;
            statuses.thumbnail_pic = thumbnail_pic;
            statuses.retweeted_status_id = retweeted_status_id;

            return statuses;
        }


        /// <summary>
        /// 获取一个包含微博信息内容的DataTable对象
        /// </summary>
        /// <param name="strStatusesXML"></param>
        /// <returns></returns>
        public static DataTable GetStatusesList(string strStatusesXML)
        {
            oAuthSina o = new oAuthSina();
            if (!string.IsNullOrEmpty(strStatusesXML))
            { 
                DataTable dt = new DataTable();
                dt.Columns.Add(new DataColumn("id", typeof(long)));
                dt.Columns.Add(new DataColumn("user_id", typeof(long)));
                dt.Columns.Add(new DataColumn("text", typeof(string)));
                dt.Columns.Add(new DataColumn("source", typeof(string)));
                dt.Columns.Add(new DataColumn("favorited", typeof(bool)));
                dt.Columns.Add(new DataColumn("truncated", typeof(bool)));
                dt.Columns.Add(new DataColumn("in_reply_to_status_id", typeof(long)));
                dt.Columns.Add(new DataColumn("in_reply_to_user_id", typeof(long)));
                dt.Columns.Add(new DataColumn("in_reply_to_screen_name", typeof(string)));
                dt.Columns.Add(new DataColumn("created_at", typeof(string)));
                dt.Columns.Add(new DataColumn("thumbnail_pic", typeof(string)));
                dt.Columns.Add(new DataColumn("original_pic", typeof(string)));
                dt.Columns.Add(new DataColumn("screen_name", typeof(string)));
                dt.Columns.Add(new DataColumn("profile_image_url", typeof(string)));

                SinaWeiboStatuses status = new SinaWeiboStatuses();
                SinaWeiboUsers user = new SinaWeiboUsers();
                WeiboXMLHandler xml = new WeiboXMLHandler();
                xml.LoadXml(strStatusesXML);

                foreach (XmlNode xn in xml.SelectNodes("/statuses/status"))
                {
                    DataRow dr = dt.NewRow();
                    status =  GetModeByStatusXML(xn);

                    dr["id"] = status.id;
                    dr["text"] = status.text;
                    dr["source"] = status.source;
                    dr["favorited"] = status.favorited;
                    dr["truncated"] = status.truncated;
                    dr["in_reply_to_status_id"] = status.in_reply_to_status_id;
                    dr["in_reply_to_user_id"] = status.in_reply_to_user_id;
                    dr["in_reply_to_screen_name"] = status.in_reply_to_screen_name;
					dr["created_at"] = eSYSU.Web.Common.StringHelper.DateStringFromNow(Convert.ToDateTime(status.created_at));
                    dr["thumbnail_pic"] = status.thumbnail_pic;
                    dr["original_pic"] = status.original_pic;

                    XmlNode xn_user = xn.SelectNodes("user")[0];
                    
                    user = GetModelByUserXml(xn_user);
                    dr["user_id"] = user.id;
                    dr["screen_name"] = user.screen_name;
                    dr["profile_image_url"] = user.profile_image_url;

                    dt.Rows.Add(dr);
                }
                return dt;
            }
            return null;
        }


        /// <summary>
        /// 获取用户的oauth令牌和密钥
        /// </summary>
        /// <param name="userID">用户ID</param>
        /// <returns>密钥字符串数组</returns>
        public static string[] GetUserAccessToken(int userID)
        {
            string sSql = String.Format("select * from weibo where wbtype ='sina' and UserID = {0}", userID);
            DataTable dt = eSYSU.Data.DataAccess.SqlHelper.GetDataTable(sSql);
            if (dt.Rows.Count > 0)
            {
                return new string[] { dt.Rows[0]["AccessToken"].ToString(), dt.Rows[0]["AccessSecret"].ToString() };
            }
            else
            {
                return null;
            }
        }


        /// <summary>
        /// 获取用户的oauth令牌和密钥
        /// </summary>
        /// <param name="userID">用户名</param>
        /// <returns>密钥字符串数组</returns>
        public static string[] GetUserAccessToken(string strUserName)
        {
            string sSql = String.Format("select accessToken,accessSecret from weibo as w,user where w.wbtype ='sina' and w.userid = user.userid and user.username = '{0}'", strUserName.ToLower().ToString());
            DataTable dt = eSYSU.Data.DataAccess.SqlHelper.GetDataTable(sSql);
            if (dt.Rows.Count > 0)
            {
                return new string[] { dt.Rows[0]["AccessToken"].ToString(), dt.Rows[0]["AccessSecret"].ToString() };
            }
            else
            {
                return null;
            }
        }


        /// <summary>
        /// 获取指定用户的微博内容
        /// </summary>
        /// <param name="userID">用户ID</param>
        /// <returns>包含微博内容XML字符串</returns>
        public static string GetWeiboXML(int userID)
        {
            oAuthSina oauth = new oAuthSina();

            string[] tok = GetUserAccessToken(userID);
            oauth.token = tok[0];
            oauth.tokenSecret = tok[1];
            string url = "http://api.t.sina.com.cn/statuses/friends_timeline.xml?count=16";

            return oauth.oAuthWebRequest(oAuthSina.Method.GET, url, String.Empty);
        }


        /// <summary>
        /// 获取指定用户的微博内容
        /// </summary>
        /// <param name="userID">用户名</param>
        /// <returns>包含微博内容XML字符串</returns>
        public static string GetWeiboXML(string strUserName)
        {
            oAuthSina oauth = new oAuthSina();

            string[] tok = GetUserAccessToken(strUserName);
            oauth.token = tok[0];
            oauth.tokenSecret = tok[1];
            string url = WeiboApiUrlSplice(2, 16);

            return oauth.oAuthWebRequest(oAuthSina.Method.GET, url, String.Empty);
        }


        /// <summary>
        /// 获取指定用户的微博内容
        /// </summary>
        /// <param name="userID">用户名</param>
        /// <param name="intType">微博内容类型，1:公共微博，2:我的关注(默认)，3:我的微博</param>
        /// <param name="intCount">返回的微博数量，限制为1~200，默认为16条</param>
        /// <returns>包含微博内容XML字符串</returns>
        public static string GetWeiboXML(string strUserName, int intType, int intCount)
        {
            oAuthSina oauth = new oAuthSina();

            string[] tok = GetUserAccessToken(strUserName);
            oauth.token = tok[0];
            oauth.tokenSecret = tok[1];
            string url = WeiboApiUrlSplice(intType, intCount);

            return oauth.oAuthWebRequest(oAuthSina.Method.GET, url, String.Empty);
        }


        /// <summary>
        /// 拼接并返回调用微博API所需的URL字符串
        /// </summary>
        /// <param name="intType">微博内容类型，1:公共微博，2:我的关注(默认)，3:我的微博</param>
        /// <param name="intCount">返回的微博数量，限制为1~200，默认为16条</param>
        /// <returns>包含微博内容XML字符串</returns>
        public static string WeiboApiUrlSplice(int intType,int intCount)
        {
            string url = "";
            switch (intType)
            {
                case 1: 
                    url = "public_timeline";
                    break;
                case 2:
                    url = "friends_timeline";
                    break;
                case 3:
                    url = "user_timeline";
                    break;
                default:
                    url = "friends_timeline";
                    break;
            }
            intCount = intCount < 1 || intCount > 200 ? 20 : intCount;
            url = "http://api.t.sina.com.cn/statuses/" + url + ".xml?count=" + intCount.ToString();
            return url;
        }
    }
}